/*
 * ENUM Discoverer. ENUM Demonstration software, demonstrating the potential of ENUM.
 * 
 * Copyright (C) 2009 SIDN and ISOC.nl
 * 
 * This file is part of ENUM Discoverer.
 *
 * ENUM Discoverer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ENUM Discoverer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ENUM Discoverer.  If not, see <http://www.gnu.org/licenses/>.
 */

package nl.sidn.enumdiscoverer.contacts.adapters;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.util.Log;
import nl.sidn.enumdiscoverer.EnumRecord;
import nl.sidn.enumdiscoverer.LogConfig;
import nl.sidn.enumdiscoverer.contacts.ContactProfileAggregator;

/**
 * Handles the 'geo' URI scheme outlined in the Internet-Draft
 * draft-mayrhofer-geopriv-geo-uri-01.
 * @author	Grant Patterson (grant.patterson@catalyst.net.nz)
 */
public class GeoAdapter implements ContactAdapter {
	
	static final String TAG = LogConfig.getLogTag(GeoAdapter.class);
	// whether DEBUG level logging is enabled (whether globally, or explicitly for this log tag)
	static final boolean DEBUG = LogConfig.isDebug(TAG);
	// whether VERBOSE level logging is enabled
	static final boolean VERBOSE = LogConfig.VERBOSE;
	
	private static final String LAT_REGEX = "-?\\d{1,2}(?:\\.\\d*)?";
	private static final String LONG_REGEX = "-?\\d{1,3}(?:\\.\\d*)?";
	// [ "-" ] *DIGIT [ "." *DIGIT ]
	private static final String ALT_REGEX = "-?\\d*(?:\\.\\d*)?";
	
	/**
	 * Regular expression describing valid geo: URIs.<br/>
	 * From draft-mayrhofer-geopriv-geo-uri-01 (in ABNF):<br/>
	 * <pre>
	 *     geo-URI       = geo-scheme ":" geo-path
	 *     geo-scheme    = "geo"
	 *     geo-path      = geo-location
	 *
	 *     geo-location   = latitude "," longitude [ "," altitude ]
	 *
	 *     latitude       = [ "-" ] 1*2DIGIT [ "." *DIGIT ]
	 *     longitude      = [ "-" ] 1*3DIGIT [ "." *DIGIT ]
	 *     altitude       = [ "-" ] *DIGIT [ "." *DIGIT ]
	 * </pre>
	 */
	public static final String REGEX = "geo:("+LAT_REGEX+"),("+LONG_REGEX+")(?:,("+ALT_REGEX+"))?";
	
	
	private final Pattern mUriPat = Pattern.compile(REGEX);
	
	@Override
	public void updateContact(String urlCapture, EnumRecord enumRecord,
			ContactProfileAggregator profileAggregator) {
		
		if (VERBOSE) Log.v(TAG, "handling " + enumRecord.getUrl());
		
		Matcher m = mUriPat.matcher(enumRecord.getUrl());
		if (!m.matches()) {
			Log.i(TAG, "Invalid geo URI: " + enumRecord.getUrl());
			return;
		}
		
		String latitude = m.group(1);
		String longitude = m.group(2);
		
		if (VERBOSE) Log.v(TAG, "Latitude=" + latitude + ", Longitude=" + longitude);
		
		int latitudeE6 = degreeStringToMicroDegreeInt(latitude);
		int longitudeE6 = degreeStringToMicroDegreeInt(longitude);
		
		profileAggregator.addLocation(latitudeE6, longitudeE6, enumRecord);
	}
	
	@Override
	public String toString() {
		return getClass().getSimpleName();
	}
	
	private int degreeStringToMicroDegreeInt(String degreeStr) {
		
		double degrees = Double.parseDouble(degreeStr);
		return (int) Math.round(degrees * 1000000);
	}
}
